using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using CultivationSkills.Skills;
using ThunderRoad;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;

namespace CultivationSkills.Utils;

[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Global")]
[SuppressMessage("ReSharper", "ConvertToConstant.Global")]
public static class SwordShoot
{
    public static ModOptionFloat[] RadiosRateOptions = ModOptionFloat.CreateArray(0, 0.2f, 0.01f);
    public static ModOptionInt[] ChargeForceOptions = ModOptionInt.CreateArray(1, 100, 1);
    public static ModOptionInt[] ItemExistenceTimeOptions = ModOptionInt.CreateArray(1, 60, 1);

    public const string DefaultItemId = "Sword-HanLiuMianBingPo-Middle";

    [ModOption(name = "Shoot Force", order = 2, category = "Sword Shoot Settings",
        interactionType = ModOption.InteractionType.Slider, valueSourceName = "ChargeForceOptions",
        saveValue = true)]
    public static int ShootForce = 20;

    [ModOption(name = "Item Existence Time", order = 3, category = "Sword Shoot Settings",
        interactionType = ModOption.InteractionType.Slider, valueSourceName = "ItemExistenceTimeOptions",
        saveValue = true)]
    public static int ItemExistenceTime = 5;

    [ModOption(name = "Random Radios Rate", order = 4, category = "Sword Shoot Settings",
        interactionType = ModOption.InteractionType.Slider, valueSourceName = "RadiosRateOptions",
        saveValue = true)]
    public static float RadiosRate = 0.04f;

    private static readonly Dictionary<string, ItemData> ItemDataMap = new Dictionary<string, ItemData>();

    private static void AlignAndPlaceItem(Item item, Vector3 position, Vector3 direction)
    {
        var child = item.flyDirRef ? item.flyDirRef : item.spawnPoint;
        if (!child)
        {
            Debug.LogError("Item " + item.data.id + " has no spawn point");
            child = item.transform;
        }

        item.transform.position = position;
        GameUtils.AlignRotate(item.transform, child.forward, direction);

        item.CacheSpawnTransformation();
    }

    public static void ShootMulti(int spawnCount, Vector3 position, Vector3 direction,
        string itemId, Vector3 fixTarget = default)
    {
        Debug.Log("发射数量：" + spawnCount);
        var itemData = GetItemData(itemId);
        if (itemData == null || !Application.isPlaying)
        {
            Debug.LogWarning("没有发射的item！");
            return;
        }

        List<Item> items = [];
        for (var index1 = 0; index1 < spawnCount; ++index1)
        {
            var random = new Vector3(Random.Range(-1.0f, 1.0f), Random.Range(-0.3f, 0.3f),
                Random.Range(-1.0f, 1.0f));
            random = Vector3.ProjectOnPlane(random * (spawnCount * RadiosRate), direction);
            var fix = fixTarget == default ? fixTarget : fixTarget + random;
            Shoot(items, itemData, position + random, direction, fix);
        }

        Debug.Log("itemSize:" + items.Count);
        MyAssets.PlayAudio(MyAudios.Shoot, position);
        Player.local.StartCoroutine(Clear(items));
    }

    private static IEnumerator Clear(List<Item> items)
    {
        yield return new WaitForSeconds(ItemExistenceTime);
        var cnt = 0;
        foreach (var item in items)
        {
            cnt++;
            GameUtils.QuickDespawn(item);
            // 确保每帧只处理一定数量的对象
            if (cnt % 10 == 0)
            {
                yield return null;
            }
        }
    }

    public static void Shoot(List<Item> items, ItemData itemData, Vector3 position, Vector3 direction,
        Vector3 fixTarget)
    {
        itemData.SpawnAsync(item =>
        {
            if (!item)
            {
                Debug.LogError("生成失败！");
                return;
            }

            items.Add(item);
            // Debug.Log(
            // $"item Layer:{item.forcedLayer}; {item.currentPhysicsLayer},{item.forcedItemLayer},{item.forceMeshLayer}");
            item.SetColliderLayer(LayerMask.GetMask(LayerName.LightProbeVolume.ToString()));
            // Debug.Log(
            // $"SetColliderLayer:{item.forcedLayer}; {item.currentPhysicsLayer},{item.forcedItemLayer},{item.forceMeshLayer}");

            item.SetOwner(Item.Owner.Player);
            item.IgnoreRagdollCollision(Player.local.creature.ragdoll);
            if (fixTarget != Vector3.zero)
            {
                // 纠正
                Debug.Log($"纠正前方向：{direction},source:{item.transform.position}");
                direction = fixTarget - item.transform.position;
                direction.Normalize();
                Debug.Log($"纠正后方向：{direction}");
            }

            AlignAndPlaceItem(item, position, direction);
            item.physicBody.velocity = direction * ShootForce;
            item.Throw(flyDetection: Item.FlyDetection.Forced);
            item.lastHandler = Player.local?.creature.handRight;
        }, position: position, pooled: false, owner: Item.Owner.Player);
    }


    public static ItemData GetItemData(string shootItemId = DefaultItemId)
    {
        if (ItemDataMap.TryGetValue(shootItemId, out var data))
        {
            return data;
        }

        if (Catalog.TryGetData<ItemData>(shootItemId, out var itemData))
        {
            ItemDataMap.Add(shootItemId, itemData);
        }

        if (itemData == null)
        {
            Debug.LogWarning("Could not find ItemData for item: " + shootItemId);
        }

        return itemData;
    }

    public static void DoSpawn(int count, string itemId = "BBY-Item-SwordSoot")
    {
        ShootMulti(count, Player.local.head.transform.position + new Vector3(0, 1, 0),
            Player.local.head.transform.forward,
            itemId);
    }
}